(1)製作頁面(元件)
src/views/Userboard.vue 產品navbar
src/views/UserCart.vue 產品總頁面/購物車 =>商品啟用才會顯示,已經寫好API
src/views/UserProduct.vue 產品各別頁面
(2)綁路徑
src/router/index.js
{
path: '/user',
component: () => import('../views/Userboard.vue'),
children: [
{
path: 'cart',
component: () => import('../views/UserCart.vue'),
},
{
path: 'product/:productId',
component: () => import('../views/UserProduct.vue'),
},
],
},
(3)製作供使用者點擊頁面
<div class="btn-group btn-group-sm">
<button
type="button"
class="btn btn-outline-secondary"
@click="getProduct(item.id)"
>
查看更多
</button>
(1)加入購物車 按鈕+事件+方法
<button
v-on:click="addCart(item.id)"
type="button"
class="btn btn-outline-danger"
>
加到購物車
</button>
(2)抓到參數(id)並送入資料庫(依照API給資料)
addCart(id) {
console.log("id", id);
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/cart`;
const cart = {
product_id: id,
qty: 1,
};
this.$http.post(url, { data: cart }).then((res) => {
console.log("res", res);
});
},
},
(1)新增倉庫
data() {
return {
status: {
// 個別小小讀取效果倉庫(購物車按鈕暫時無法執行)
loadingItem: "", //對應品項id
},
};
},
(2)將值寫入倉庫,供未來比對用
按下按鈕送id,賦值給倉庫
addCart(id) {
this.status.loadingItem = id; // 按下按鈕送id,賦值給倉庫
};
this.$http.post(url, { data: cart }).then((res) => {
this.status.loadingItem = ""; //資料庫更新成功後,空
});
},
(2)製作 不能按(disabled) 樣式並寫入觸發條件
如果倉庫收到的值 === 當前id
<button
v-bind:disabled="this.status.loadingItem === item.id"
class="btn btn-outline-danger"
>
加到購物車
</button>
如果倉庫收到的值 === 當前id
<div
v-if="this.status.loadingItem === item.id"
class="spinner-grow spinner-grow-sm text-danger"
role="status"
>
<span class="visually-hidden">Loading...</span>
目標:新增查看購物車內容 及 購物車Icon增加
getCart() {
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/cart`;
this.$http.get(url).then((response) => {
console.log("抓購物車內容", response);
this.cart = response.data.data;
this.isLoading = false;
});
},
(2)購物車內容渲染網頁上
data() {
return {
cart: {},
coupon_code: "",
};
},
<tr v-for="item in cart.carts" :key="item.id">
https://icons.getbootstrap.com/
(1)安裝 Bootstrap Icon
npm i bootstrap-icons
(2)匯入
main.js
//bootstrap Icons
import "bootstrap-icons/font/bootstrap-icons.css";
(3)使用
<span class="material-icons-outlined"> backspace </span>
我是使用 material-icons XD
https://www.npmjs.com/package/material-icons
說明:購物車總金額由 後端 計算
(1)限制最低數量1 min
(2)product_id(String)、qty(Number)傳遞後端才能計算總金額
updateCart(item) {
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/cart/${item.id}`;
this.isLoading = true;
const cart = {
product_id: item.product_id,
qty: item.qty,
};
this.$http.put(url, { data: cart }).then((res) => {
console.log("res", res);
this.getCart();
});
},
(3)補做讀取中暫時無法使用function
<input
:disabled="item.id === status.loadingItem"
/>
data() {
return {
status: {
// 小小讀取效果 + 購物車按鈕暫時無法執行 倉庫
loadingItem: "", //對應品項id
},
updateCart(item) {
this.status.loadingItem = item.id; // 按下按鈕送id,賦值給倉庫
const cart = {
product_id: item.product_id,
qty: item.qty,
};
this.$http.put(url, { data: cart }).then((res) => {
this.status.loadingItem = ""; // 按下按鈕送id,賦值給倉庫
this.getCart();
});
},
(1)先在後台增加好優惠卷 並 啟用
shop666
(2)抓折扣碼的值,透過後端計算
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/coupon`;
const coupon = {
code: this.coupon_code,
};
(3)渲染在畫面上
<!-- 如果不相同 顯示此tr -->
<tr v-if="cart.final_total !== cart.total">
<td colspan="3" class="text-end text-success">折扣價</td>
<td class="text-end text-success">
{{ $filters.currency(cart.final_total) }}
</td>
</tr>
(1)Cli 中引入外部套件vee-validate
1-1. 安裝vee-validate套件
npm install vee-validate@next --save
1-2. 安裝vee-validate套件
https://vee-validate.logaretm.com/v4/guide/global-validators#vee-validaterules
npm install @vee-validate/rules
1-3. 安裝vee-validate套件
https://vee-validate.logaretm.com/v4/guide/i18n#using-vee-validatei18n
npm install @vee-validate/i18n
若serve正在跑的話 要先停止(ctrl+C)
1-4. 匯入main.js
import { Form, Field, ErrorMessage, defineRule, configure } from "vee-validate";
import AllRules from "@vee-validate/rules";
import { localize, setLocale } from "@vee-validate/i18n";
import zhTW from "@vee-validate/i18n/dist/locale/zh_TW.json";
//製作 vee-validate 裡面的方法都抓出來用
Object.keys(AllRules).forEach((rule) => {
defineRule(rule, AllRules[rule]);
});
configure({
generateMessage: localize({ zh_TW: zhTW }), // 載入繁體中文語系
validateOnInput: true, // 當輸入任何內容直接進行驗證
});
// 設定預設語系
setLocale("zh_TW");
// vee-validate引用
app.component('Form', Form);
app.component('Field', Field);
app.component('ErrorMessage', ErrorMessage);
1-5.使用 Form、Field、ErrorMessage標籤,及 格式錯誤回報
v-slot 插入文字or外部標籤 vee-validate套件用法 引入zh_TW.json
邏輯:
1.利用v-slot抓全部的zh_TW.json
2.再靠rules="email|required"判斷 是否違反格式
3.若違反 v-slot 顯示錯誤訊息文字
(1)建立API需要的倉庫
// 表單資料
form: {
user: {
name: "",
email: "",
tel: "",
address: "",
},
message: "",
},
(2)html 抓輸入的值送倉庫 v-model
<Form class="col-md-6" v-slot="{ errors }" @submit="createOrder">
<div class="mb-3">
<label for="address" class="form-label">收件人地址</label>
<Field
id="address"
name="地址"
type="text"
class="form-control"
:class="{ 'is-invalid': errors['地址'] }"
placeholder="請輸入地址"
rules="required"
v-model="form.user.address"
></Field>
createOrder() {
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/order`;
const order = this.form;
this.$http.post(url, { data: order }).then((res) => {
console.log(res);
});
},
目標:製作 送出訂單後轉址 及 確認訂單頁面
(1)製作頁面元件
src/views/UserCheckout.vue
利用UserCart.vue送出訂單紐,送出orderID(Ex:-MofhSJGMRQSvlrWFZfU)
orderID抓資料回放到UserCheckout.vue確認訂單頁面
http://localhost:8080/#/user/checkout/-MofhSJGMRQSvlrWFZfU
(後端API方法)
created() {
// $route.params 抓網址列用
this.id = this.$route.params.productId;
this.getProduct();
},
(2)綁Router (checkout/:orderId)
src/router/index.js
path: "/user",
component: () => import("../views/Userboard.vue"),
children: [
{
path: "cart",
component: () => import("../views/UserCart.vue"),
},
{
path: "product/:productId",
component: () => import("../views/UserProduct.vue"),
},
{
path: 'checkout/:orderId',
component: () => import('../views/UserCheckout.vue'),
},
(3)製作供使用者點擊可連結的按鈕
<Form class="col-md-6" v-slot="{ errors }" @submit="createOrder">
createOrder() {
this.isLoading = true;
const url = `${process.env.VUE_APP_API}api/${process.env.VUE_APP_PATH}/order`;
const order = this.form;
this.$http.post(url, { data: order }).then((res) => {
console.log(res); // orderId
this.isLoading = false;
// 後端有方法會直接清空購物車
this.getCart();
// 抓ID送轉跳網址列
this.orderId = res.data.orderId;
this.$router.push(`checkout/${this.orderId}`);
});
},
<tr v-if="cart.final_total !== cart.total">
<td colspan="3" class="text-end text-success">折扣價</td>
<td class="text-end text-success">
{{ $filters.currency(cart.final_total) }}
</td>
</tr>
<span v-if="item.is_enabled === 1" class="text-success">啟用</span>
<span v-else class="text-muted">未起用</span>
:class="{ active: page === pages.current_page }"
class="page-item"
<button
v-bind:disabled="this.status.loadingItem === item.id"
type="button"
class="btn btn-outline-danger"
>
(1)查看套件資料 package.json
(2)刪除套件
npm remove ???
npm remove element-ui
npm remove babel-plugin-component